module Utilities
  module HexDump
    LengthSpacer = " " *  2
    TextSpacer = " " *  2
    MiddleSpacer = " " * 2
    Width = 16
    HalfWay = (Width - 1) / 2

    def process_hex_values(line, line_count)
      output = "%08d" % (line_count*Width) + LengthSpacer
      char_count = 0
      line.each_byte do |ch|
        output << "%02X" % ch + " "
        output << MiddleSpacer if char_count == HalfWay
        line[char_count,1] = "." if ch < 32
        char_count = char_count.next
      end
      output
    end

    def dump(data)
      lines ||= []
      (data.length / Width).times { |i| lines.push data[i*Width, Width] }
      output = ""
      line_count = 0
      lines.each do |line|
        output << process_hex_values(line, line_count)
        output << TextSpacer + line
        output << "\n" if (line_count != lines.length - 1)
        line_count = line_count.next
      end

      last_line = data[lines.length*Width, Width]
      if (last_line != "")
        output << "\n" if lines.length > 0
        output << process_hex_values(last_line, line_count)
        char_count = 0
        (Width - last_line.length).times do
          output << "   "
          output << MiddleSpacer if char_count == HalfWay
          char_count = char_count.next
        end
        output << TextSpacer + last_line
      end
      output << "\n"
    end
  end
end

if __FILE__ == $0
  class Test
    include Utilities::HexDump
    def test_dump(data)
      dump data
    end
  end

  test = Test.new
  puts test.dump("\0 23456789012345678901234567890123")
  puts test.dump("testj")

end